﻿#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<vector>
#include<list>
#include<string>
using namespace std;
//int main()
//{
//	int i = 0;
//	const int ci = 0;
//	const int& rci = ci;
//	decltype(i) m = 1; // m的类型是int
//	decltype(ci) x = 1; // x的类型是const int
//	m++;
//	//x++; // 报错
//	decltype(rci) y = x; // y的类型是const int&
//	//y++; // 报错
//	//decltype(rci) z; // 报错
//	int* p1 = &i;
//	decltype(p1) p2 = nullptr; // p2的类型是int*
//	// 特殊处理
//	decltype(*p1) r1 = i; // r1的类型是int&，解引⽤表达式推导出的内容是引⽤
//	decltype(i) r2;
//	// r3的类型是int&, (i)是⼀个表达式，变量是⼀种可以赋值特殊表达式，
//	// 所以会推出引⽤类型
//	decltype((i)) r3 = i; 
//	
//	return 0;
//}

//template <typename T>
//class A
//{
//	public :
//	void func(T& container)
//	{
//		_it = container.begin();
//	}
//private:
//	// 这⾥不确定是iterator还是const_iterator，也不能使⽤auto
//	//typename T::iterator _it;
//	// 使⽤decltype推导就可以很好的解决问题
//	decltype(T().begin()) _it;
//};
//int main()
//{
//	const vector<int> v1;
//	A<const vector<int>> obj1;
//	obj1.func(v1);
//	vector<int> v2;
//	A<vector<int>> obj2;
//	obj2.func(v2);
//	//decltype在lambda表达式中也能用的应用
//	auto lambda1 = [](int x, int y) { return x + y; };
//	decltype(lambda1) lambda2 = lambda1;  // 复制构造
//
//	// 使用
//	std::cout << lambda1(5, 3) << std::endl;  // 8
//	std::cout << lambda2(5, 3) << std::endl;  // 8
//	return 0;
//}



template<class R, class Iter>
R Func(Iter it1, Iter it2)
{
	R x = *it1;
	++it1;
	while (it1 != it2)
	{
		x += *it1;
		++it1;
	} 
	return x;
} 
// 不⽀持这样写，因为C++是前置语法，编译器遇到对象只会向前搜索
//template<class Iter>
//decltype(*it1) Func(Iter it1, Iter it2)
//{
// auto& x = *it1;
// ++it1;
// while (it1 != it2)
// {
// x += *it1;
// ++it1;
// }
// return x;
//}
// 返回位置⽤auto，函数后⾯接->推导返回类型的位置返回值⽅式
// 要注意decltype(*it1)推导出的是引⽤类型
//template<class Iter>
//auto Func(Iter it1, Iter it2)->decltype(*it1)
//{
// auto& x = *it1;
// ++it1;
// while (it1 != it2)
// {
// x += *it1
// ++it1;
// }
// return x;
//}
int main()
{
	vector<int> v = { 1,2,3 };
	list<string> lt = { "111","222","333" };
	// 这⾥⽆法调⽤上⾯的函数，因为函数模板只能通过实参推导模板类型，⽆法推导R
	//auto ret1 = Func(v.begin(), v.end());
	//auto ret2 = Func(lt.begin(), lt.end());
	// 显⽰实例化能解决问题，但是调⽤就很⿇烦
	auto ret1 = Func<decltype(*v.begin())>(v.begin(), v.end());
	auto ret2 = Func<decltype(*lt.begin())>(lt.begin(), lt.end());
	cout << ret1 << endl;
	cout << ret2 << endl;
	return 0;
}
//decltype(auto) 
int main()
{
	int i = 0;
	int& ri = i;
	const int ci = 42; // 顶层const
	int* const p1 = &i; // 顶层const
	const int* p2 = &ci; // 底层const
	auto j = ri; // j类型为int
	decltype(auto) j1 = ri; // j1类型为int&
	++j1;
	auto r1 = ci; // r1类型为int，忽略掉顶层const
	decltype(auto) rr1 = ci; // rr1类型为const int
	r1++;
	//rr1++;
	auto r2 = p1; // r2类型为int*，忽略掉顶层const
	decltype(auto) rr2 = p1; // rr1类型为int* const
	r2++;
	//rr2++;
	auto r3 = p2; // r3类型为const int*，保留底层const
	decltype(auto) rr3 = p2; // rr3类型为const int*
	// (*rr3)++;
	return 0;
}


// 1. 复杂返回类型
auto getComplexType() -> std::map<std::string, std::vector<int>> {
	// ...
}
// 2. 依赖参数类型的返回类型
template <typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
	return t + u;
}
// 3. lambda表达式
auto lambda = [](int x) -> double { return x * 1.5; };